package com.sumer.psychology.sharing.domain.model;

import com.sumer.psychology.common.Assert;
import com.sumer.psychology.common.BusinessException;
import com.sumer.psychology.common.domain.model.*;
import com.sumer.psychology.tag.domain.model.AbstractTaggedEntity;
import com.sumer.psychology.tag.domain.model.TagDomainRegistry;
import com.sumer.psychology.tag.domain.model.Tag;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * 分享资源
 * <p/>
 * User: zhenguang.zhu
 * Date: 2014/9/9
 * Time: 15:16
 */
public class SharedResource extends AbstractTaggedEntity {
    private SharedResourceId sharedResourceId;
    private String topic;
    private Availability availability;
    private Author author;
    private Date createTime;
    private Date lastModifyTime;

    private int	viewCnt;
    private	int downCnt;
    private Tag	tag;
    
    private Set<SharedFile> sharedFiles = new HashSet<>(5);

    /**
     * 创建一个分享
     *
     * @param sharedResourceId id
     * @param topic topic
     * @param author author
     * @param sharedFiles files
     */
    public SharedResource(SharedResourceId sharedResourceId, String topic, Author author, Set<SharedFile> sharedFiles) {
        setSharedResourceId(sharedResourceId);
        setTopic(topic);
        setSharedFiles(sharedFiles);
        setAuthor(author);
        setAvailability(Availability.ACTIVE);
        setCreateTime(new Date());

        apply(new SharedResourceCreatedEvent(
                sharedResourceId(),
                topic(),
                author(),
                sharedFiles()));
    }

    public SharedResource() {
    }

    /**
     * 共享文件的数量
     *
     * @return count
     */
    public int sharedFilesCount() {
        return sharedFiles.size();
    }

    /*
     * 替换全部分享文件
     */
    private void replaceSharedFiles(Set<SharedFile> sharedFiles) {
        sharedFiles().clear();
        setSharedFiles(sharedFiles);
    }

    /**
     * 修改分享
     *
     * @param topic topic
     * @param sharedFiles shared files
     */
    public void change(String topic, Set<SharedFile> sharedFiles) {
        setTopic(topic);
        replaceSharedFiles(sharedFiles);
        setLastModifyTime(new Date());

        apply(new SharedResourceChangedEvent(
                sharedResourceId(),
                topic(),
                sharedFiles()));
    }

    /**
     * 删除分享
     */
    public void delete() {
        setAvailability(Availability.DELETED);
        setLastModifyTime(new Date());

        apply(new SharedResourceDeletedEvent(sharedResourceId()));
    }

    @Override
    protected void afterReplaceTags() {
        setLastModifyTime(new Date());

        apply(new SharedResourceTagReplacedEvent(
                sharedResourceId(),
                tags(),
                removedTags()));
    }

    @Override
    protected void beforeReplaceTags(Set<Tag> tags) {
        if (!TagDomainRegistry.tagService().areAllResourceTags(tags)) {
            throw new BusinessException("标签类型错误");
        }
    }

    private void setSharedResourceId(SharedResourceId sharedResourceId) {
        Assert.notNull(sharedResourceId, "id不能为空");
        Assert.notEmpty(sharedResourceId.identity(), "id不能为空");

        this.sharedResourceId = sharedResourceId;
    }

    private void setTopic(String topic) {
        Assert.length(topic, 200, "主题不能超过100个字");

        this.topic = topic;
    }

    private void setSharedFiles(Set<SharedFile> sharedFiles) {
        Assert.notEmpty(sharedFiles, "至少有一个分享文件");

        this.sharedFiles = sharedFiles;
    }

    private void setAvailability(Availability availability) {
        Assert.notNull(availability, "可用性不能为空");

        this.availability = availability;
    }

    private void setCreateTime(Date createTime) {
        Assert.notNull(createTime, "创建日期不能为空");

        this.createTime = createTime;
    }

    public void setAuthor(Author author) {
        Assert.notNull(author, "作者不能为空");
        Assert.notEmpty(author.identity(), "作者id不能为空");

        this.author = author;
    }

    private void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }

    public SharedResourceId sharedResourceId() {
        return sharedResourceId;
    }

    public String topic() {
        return topic;
    }

    public Availability availability() {
        return availability;
    }

    public Date createTime() {
        return createTime;
    }

    public Date lastModifyTime() {
        return lastModifyTime;
    }

    private Set<SharedFile> sharedFiles() {
        return sharedFiles;
    }

    public Author author() {
        return author;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        SharedResource that = (SharedResource) o;

        if (author != null ? !author.equals(that.author) : that.author != null) return false;
        if (availability != that.availability) return false;
        if (sharedFiles != null ? !sharedFiles.equals(that.sharedFiles) : that.sharedFiles != null) return false;
        if (sharedResourceId != null ? !sharedResourceId.equals(that.sharedResourceId) : that.sharedResourceId != null)
            return false;
        if (topic != null ? !topic.equals(that.topic) : that.topic != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = sharedResourceId != null ? sharedResourceId.hashCode() : 0;
        result = 31 * result + (topic != null ? topic.hashCode() : 0);
        result = 31 * result + (availability != null ? availability.hashCode() : 0);
        result = 31 * result + (author != null ? author.hashCode() : 0);
        result = 31 * result + (sharedFiles != null ? sharedFiles.hashCode() : 0);
        result = 31 * result +  this.downCnt *17;
        result = 31 * result +  this.viewCnt *17;
        result = 31 * result +   (this.tag != null ? this.tag.hashCode() : 0)  *17;
        return result;
    }

    @Override
	public String toString() {
		return "SharedResource [sharedResourceId=" + sharedResourceId
				+ ", topic=" + topic + ", availability=" + availability
				+ ", author=" + author + ", createTime=" + createTime
				+ ", lastModifyTime=" + lastModifyTime + ", viewCnt=" + viewCnt
				+ ", downCnt=" + downCnt + ", tag=" + tag + ", sharedFiles="
				+ sharedFiles + "]";
	}

}
